#ifndef _VECTRAIT6272011_H_
#define _VECTRAIT6272011_H_

#include 

template <class T, int D>
struct raw_vector {
	typedef T Type;
	static const int Demension = D;

	union {
		struct { Type x, y; };
		Type data[D];
	};

	raw_vector() { x = y = 0; }
	raw_vector(Type _x, Type _y) { x = _x, y = _y; }

	Type cross(const raw_vector<T, D>& op) {
		return x * op.y - y * op.x;
	}
};

template <class T>
struct raw_vector<T, 3> {
	typedef T Type;
	static const int Demension = 3;

	union {
		struct { Type x, y, z; };
		Type data[3];
	};


	raw_vector() { x = y = z = 0; }
	raw_vector(Type _x, Type _y, Type _z) { x = _x, y = _y, z = _z; }

	raw_vector<T, 3> cross(const raw_vector<T, 3>& op) {
		return raw_vector<T, 3>(y*op.z-z*op.y, z*op.x-x*op.z, x*op.y-y*op.x);
	}
};

template <class T>
struct raw_vector<T, 4> {
	typedef T Type;
	static const int Demension = 4;

	union {
		struct { Type x, y, z, w; };
		Type data[4];
	};

	raw_vector() { x = y = z = w = 0; }
	raw_vector(Type _x, Type _y, Type _z, Type _w) { x = _x, y = _y, z = _z, w = _w; }

	// TODO: should this function be here? is it meaning full for vector4 to have a 
	// cross product. 
	raw_vector<T, 4> cross(const raw_vector<T, 4>& op) {
		return raw_vector<T, 4>(y*op.z-z*op.y, z*op.x-x*op.z, x*op.y-y*op.x, 1);
	}
};

template <class T, int D>
struct nonhomogeneous_vector: public raw_vector<T, D> {
	typedef typename T Type;
	static const int Demension = D;

	// constructors
	nonhomogeneous_vector() : raw_vector() {}
	nonhomogeneous_vector(Type _x, Type _y) : raw_vector(_x, _y) {};
	nonhomogeneous_vector(Type _x, Type _y, Type _z) : raw_vector(_x, _y, _z) {}
	nonhomogeneous_vector(Type _x, Type _y, Type _z, Type _w) : raw_vector(_x, _y, _z, _w) {}

	nonhomogeneous_vector(const raw_vector& op) {
		for (int i = 0; i < Demension; i ++) {
			data[i] = op.data[i];
		}
	}

	// onohomogeneous vecter properties
	inline float square_length() const {
		float result = 0.0f;
		for (int i = 0; i < Demension; i ++) {
			result += data[i] * data[i];
		}
		return result;
	}

	inline float length() const {
		return sqrt(square_length());
	}

	inline Type dot(const nonhomogeneous_vector& op) const {
		Type result = 0;
		for (int i = 0; i < Demension; i ++) {
			result += data[i] * op.data[i];
		}
		return result;
	}
};

template <class T>
struct homogeneous_vector: public raw_vector<T, 4> {
	typedef typename T Type;
	static const int Demension = 4;
	static const int hIndex = 3;

	homogeneous_vector() : raw_vector() { w = 1; }
	homogeneous_vector(Type _x, Type _y, Type _z) : raw_vector(_x, _y, _z, 1) {}
	homogeneous_vector(Type _x, Type _y, Type _z, Type _w) : raw_vector(_x, _y, _z, _w) {}

	homogeneous_vector(const raw_vector& op) {
		for (int i = 0; i < Demension; i ++) {
			data[i] = op.data[i];
		}
	}

	// onohomogeneous vecter properties
	void normalize() {
		if (!is_zero(data[hIndex])) {
			for (int i = 0; i < Demension; i ++) {
				data[i] /= data[hIndex];
			}
		}
	}

	bool is_normalized() {
		return is_zero(data[hIndex]) && is_zero(data[hIndex] - 1);
	}

	// TODO: should we call nomalize() before any other operation?
	inline float square_length() const {
		// TODO: add the assertion when we have assertion mechanism.
		// assert(is_nomalized());

		if (is_zero(data[hIndex])) return FLOAT_INF;

		float result = 0.0f;
		for (int i = 0; i < Demension - 1; i ++) {
			result += data[i] * data[i];
		}
		return result;
	}

	inline float length() const {
		if (is_zero(data[hIndex])) return FLOAT_INF;

		return sqrt(square_length());
	}

	inline Type dot(const homogeneous_vector& op) const {
		Type result = 0;
		for (int i = 0; i < Demension - 1; i ++) {
			result += data[i] * op.data[i];
		}
		return result;
	}
};

// we must put the classes that will use it self as function parameters
// down to the leaves, cause compile time poly morphism only can invoke its 
// parents' nonoverrided functions rightly.
// I am crazy, the only one thing is that I want to direct use a.x a.y a.z.
template <class _raw_type>
class computable_vector: public _raw_type
{
public:
	typedef typename _raw_type::Type Type;
	static const int Demension = _raw_type::Demension;

public: 
	// constructors
	computable_vector() : _raw_type() {
	}

	computable_vector(Type _x, Type _y) : _raw_type(_x, _y) {
	}

	computable_vector(Type _x, Type _y, Type _z) : _raw_type(_x, _y, _z) {
	}

	computable_vector(Type _x, Type _y, Type _z, Type _w) : _raw_type(_x, _y, _z, _w) {
	}
public:
	computable_vector operator+(const computable_vector& op) {
		computable_vector result;
		for (int i = 0; i < Demension; i ++) {
			result.data[i] = data[i] + op.data[i];
		}
		return result;
	}

	void operator+=(const computable_vector& op) {
		for (int i = 0; i < Demension; i ++) {
			data[i] += op.data[i];
		}
	}

	computable_vector operator-(const computable_vector& op) {
		computable_vector result;
		for (int i = 0; i < Demension; i ++) {
			result.data[i] = data[i] - op.data[i];
		}
		return result;
	}

	void operator-=(const computable_vector& op) {
		for (int i = 0; i < Demension; i ++) {
			data[i] -= op.data[i];
		}
	}

	computable_vector operator*(Type op) {
		computable_vector result;
		for (int i = 0; i < Demension; i ++) {
			result.data[i] = data[i] * op;
		}
		return result;
	}

	void operator*=(Type op) {
		for (int i = 0; i < Demension; i ++) {
			data[i] *= op;
		}
	}

	computable_vector operator/(Type op) {
		computable_vector result;
		for (int i = 0; i < Demension; i ++) {
			result.data[i] = data[i] / op;
		}
		return result;
	}

	void operator/=(Type op) {
		for (int i = 0; i < Demension; i ++) {
			data[i] /= op;
		}
	}

	Type dot(const computable_vector& op) {
		Type result = 0;
		for (int i = 0; i < Demension; i ++) {
			result += data[i] * op.data[i];
		}
		return result;
	}

	template <class OT, class op_raw_type>
	friend computable_vector operator*(OT op, const computable_vector& vec);
};

template<class OT, class op_raw_type>
computable_vector<op_raw_type> operator*(OT op, 
	const computable_vector<op_raw_type>& vec) {
	computable_vector<op_raw_type> result;
	for (int i = 0; i < op_raw_type::Demension; i ++) {
		result.data[i] = op * vec.data[i];
	}
	return result;
}

template <class T, int N>
struct color_vector {
	typedef T Type;
	static const int Demension = N;

	union {
		struct { T r, g, b; };
		T data[N];
	};

	color_vector() { r = g = b = 0; }
	color_vector(Type _r, Type _g, Type _b) { r = _r, g = _g, b = _b; }
};

template <class T>
struct color_vector<T, 4> {
	typedef T Type;
	static const int Demension = 4;

	union {
		struct { T r, g, b, a; };
		T data[4];
	};

	color_vector() { r = g = b = a = 0; }
	color_vector(Type _r, Type _g, Type _b, Type _a) { r = _r, g = _g, b = _b, a = _a; }
};


template <class T, int D, int UB, int LB>
class bounded_color_vector: public color_vector<T, D> {
public:
	typedef T Type;
	static const int Demension = D;
	static const Type upper_bound = UB;
	static const Type lowwer_bound = LB;

public:
	bounded_color_vector() : color_vector() {}
	bounded_color_vector(Type _r, Type _g, Type _b, Type _a) : color_vector(_r, _g, _b, _a) {}

	bool validate() {
		for (int i = 0; i < D; i ++) {
			if (data[i] < lowwer_bound || data[i] > upper_bound) 
				return false;
		}
		return true;
	}

	void make_validate() {
		for (int i = 0; i < D; i ++) {
			if (data[i] < lowwer_bound) data[i] = lowwer_bound;
			else if (data[i] > upper_bound) data[i] = upper_bound;
		}
	}
};

#endif //_VECTRAIT6272011_H_